package com.tn.openrpc.serialization;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import org.apache.commons.io.IOUtils;

/**
 * An implementation of <code>Serializer</code> the uses the standard Java serialization to serialize and de-serialize
 * objects.
 */
public class DefaultSerializer implements Serializer<byte[]>
{
  /**
   * {@inheritDoc}
   */
  @Override
  public byte[] serialize(Object subject) throws SerializationException
  {
    ByteArrayOutputStream byteArrayOutputStream = null;
    ObjectOutputStream objectOutputStream = null;

    try
    {
      byteArrayOutputStream = new ByteArrayOutputStream();
      objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);

      objectOutputStream.writeObject(subject);

      return byteArrayOutputStream.toByteArray();
    }
    catch (IOException e)
    {
      throw new SerializationException("An error occurred serializing object: " + subject, e);
    }
    finally
    {
      IOUtils.closeQuietly(objectOutputStream);
      IOUtils.closeQuietly(byteArrayOutputStream);
    }

  }

  /**
   * {@inheritDoc}
   */
  @Override
  public <S> S deserialize(byte[] source) throws SerializationException
  {
    ByteArrayInputStream byteArrayInputStream = null;
    ObjectInputStream objectInputStream = null;

    try
    {
      byteArrayInputStream = new ByteArrayInputStream(source);
      objectInputStream = new ObjectInputStream(byteArrayInputStream);

      //noinspection unchecked
      return (S) objectInputStream.readObject();
    }
    catch (IOException e)
    {
      throw new SerializationException("An error occurred de-serializing object", e);
    }
    catch (ClassNotFoundException e)
    {
      throw new SerializationException("Could not find class to de-serialize to", e);
    }
    finally
    {
      IOUtils.closeQuietly(objectInputStream);
      IOUtils.closeQuietly(byteArrayInputStream);
    }
  }
}
